from datetime import datetime
import json
import traceback
from django.http import JsonResponse
from django.views.generic import View
from ..models.dimensionModel import *
from django.db.models import Q, Count
from ..serializers.dimensionSerializer import *
from django.core.paginator import Paginator
from utils.encryptionAndDecryptionUtil import get_user_from_useraccount, get_useraccount_from_request
from ..config.message_config import *
from ..utils.common_util.basic_util import get_order_list_combined
from django.db import IntegrityError, transaction
from ..utils.related_util.used_util import is_dimension_used
from utils.responseContentUtil import *


def flatten(nested_list):
    flat_list = []
    for item in nested_list:
        if isinstance(item, list):
            flat_list.extend(flatten(item))  # 递归处理嵌套的列表
        else:
            flat_list.append(item)
    return flat_list


class DimensionView(View):
    def get(self, request):
        res = {"code": 400, "message": "", "data": None}
        try:
            data = request.GET
            query_list_serializer = DimensionListQuerySerializer(data=data)
            data_valid = query_list_serializer.is_valid()
            if not data_valid:
                return make_get_error_response(message=query_list_serializer.errors)
            data = query_list_serializer.validated_data
            query = Q()
            query &= Q(valid_flag=True)
            if "dimension_name" in data:
                query &= (Q(dimension_name__icontains=data["dimension_name"]) | Q(
                    dimension_name_en__icontains=data["dimension_name"]))
            if "sei_id" in data:
                query &= Q(sei_id__icontains=data["sei_id"])
            if "basic_dimension_composition" in data:
                basic_dimension_uuid_list = data["basic_dimension_composition"]

                basic_dimension_uuid_list = flatten(basic_dimension_uuid_list)
                dimensions = Dimension.objects.filter(query).annotate(
                    num_basic_dimensions=Count('dimensionmap', filter=Q(
                        dimensionmap__basic_dimension__uuid__in=basic_dimension_uuid_list))
                ).filter(
                    num_basic_dimensions__gte=len(basic_dimension_uuid_list)
                ).distinct()
            else:
                dimensions = Dimension.objects.filter(query)
            order_list_combined = get_order_list_combined(data)
            if len(order_list_combined) == 0:
                dimensions = dimensions.order_by("-create_date")
            else:
                dimensions = dimensions.order_by(*order_list_combined)
            page_size = data["page_size"]
            current_page = data["current_page"]
            total_count = dimensions.count()
            paginator = Paginator(dimensions, page_size)
            if current_page > paginator.num_pages:
                current_page = paginator.num_pages
            page_obj = paginator.get_page(current_page)
            res_data = {}
            res_data["current_page"] = current_page
            res_data["page_size"] = page_size
            res_data["total_count"] = total_count
            dimension_list_serializer = DimensionListSerializer(
                page_obj, many=True)
            res_data["objects"] = dimension_list_serializer.data
            return make_get_success_response(data=res_data)
        except Exception as e:
            traceback.print_exc()
            return make_server_error_response(str(e))

    def post(self, request):
        res = {"code": 400, "message": "", "data": None}
        try:
            user_name = get_useraccount_from_request(request=request)
            user_name = get_user_from_useraccount(user_name)
            data = json.loads(request.body)
            create_serializer = DimensionCreateSerializer(data=data)
            data_valid = create_serializer.is_valid()
            if not data_valid:
                res["code"] = 400
                res_message = "参数错误:\n"
                if "dimension_name" in create_serializer.errors:
                    res_message += "量纲中文名称已存在;\n"
                if "dimension_name_en" in create_serializer.errors:
                    res_message += "量纲英文名称已存在;\n"
                if "sei_id" in create_serializer.errors:
                    res_message += "编码已存在;\n"
                return make_create_error_response(message=res_message)
            data = create_serializer.validated_data
            basic_dimension_composition_json = {}
            if "basic_dimension_composition" in data:
                basic_dimension_composition_json = data.pop(
                    "basic_dimension_composition")
            try:
                with transaction.atomic():
                    dimension = Dimension.objects.create(
                        **data, create_person=user_name, modify_person=user_name)
                    for key, value in basic_dimension_composition_json.items():
                        if value != None and value != 0:
                            DimensionMap.objects.create(
                                basic_dimension_id=key, dimension=dimension, power=value)
            except IntegrityError as e:
                return make_create_error_response(message=str(e))
            return make_create_success_response(data=None)
        except Exception as e:
            traceback.print_exc()
            return make_server_error_response(str(e))


class DimensionInfoView(View):
    def get(self, request, uuid):
        res = {"code": 400, "message": "", "data": None}
        try:
            get_params = request.GET
            info_get_type = get_params.get("type", "")
            dimension = Dimension.objects.filter(
                uuid=uuid, valid_flag=True).first()
            if dimension is None:
                return make_get_error_response(message="该条目不存在")
            if info_get_type == "modify":
                dimension_serializer = DimensionModifyInfoSerializer(dimension)
            else:
                dimension_serializer = DimensionInfoSerializer(dimension)
            return make_get_success_response(data=dimension_serializer.data)
        except Exception as e:
            traceback.print_exc()
            return make_server_error_response(str(e))

    def put(self, request, uuid):
        res = {"code": 400, "message": "", "data": None}
        try:
            user_name = get_useraccount_from_request(request=request)
            user_name = get_user_from_useraccount(user_name)
            data = json.loads(request.body)
            dimension = Dimension.objects.filter(
                uuid=uuid, valid_flag=True).first()
            if dimension is None:
                res["code"] = 400
                res["message"] = "该条目不存在"
                return JsonResponse(res)
            modify_serializer = DimensionModifyInfoInSerializer(
                dimension, data=data)
            data_valid = modify_serializer.is_valid()
            if not data_valid:
                res["code"] = 400
                res_message = "参数错误:\n"
                if "dimension_name" in modify_serializer.errors:
                    res_message += "量纲中文名称已存在;\n"
                if "dimension_name_en" in modify_serializer.errors:
                    res_message += "量纲英文名称已存在;\n"
                if "sei_id" in modify_serializer.errors:
                    res_message += "编码已存在;\n"
                return make_update_error_response(message=res_message)
            data = modify_serializer.validated_data
            basic_dimension_composition_json = {}
            if "basic_dimension_composition" in data:
                basic_dimension_composition_json = data.pop(
                    "basic_dimension_composition")
            dealed_basic_dimension_composition_json = {}
            for key, value in basic_dimension_composition_json.items():
                if value == None or value == 0:
                    continue
                dealed_basic_dimension_composition_json[key] = value
            basic_dimension_composition_json = dealed_basic_dimension_composition_json
            basic_dimension_modify = []
            basic_dimension_create = []
            basic_dimension_delete = []
            for key, value in basic_dimension_composition_json.items():
                if DimensionMap.objects.filter(basic_dimension_id=key, dimension=dimension).exists():
                    basic_dimension_modify.append((key, value))
                else:
                    basic_dimension_create.append((key, value))
            for dimension_map in dimension.dimensionmap_set.all():
                if str(dimension_map.basic_dimension.uuid) not in basic_dimension_composition_json:
                    basic_dimension_delete.append(
                        str(dimension_map.basic_dimension.uuid))
            try:
                with transaction.atomic():
                    for field, value in data.items():
                        setattr(dimension, field, value)
                    dimension.modify_person = user_name
                    dimension.save()
                    for key, value in basic_dimension_create:
                        DimensionMap.objects.create(
                            basic_dimension_id=key, dimension=dimension, power=value)
                    for key, value in basic_dimension_modify:
                        dimension_map = DimensionMap.objects.filter(
                            basic_dimension_id=key, dimension=dimension).first()
                        dimension_map.power = value
                        dimension_map.save()
                    for key in basic_dimension_delete:
                        dimension_map = DimensionMap.objects.filter(
                            basic_dimension_id=key, dimension=dimension).first()
                        dimension_map.delete()
            except IntegrityError as e:
                return make_update_error_response(message=str(e))
            return make_update_success_response(data=None)
        except Exception as e:
            traceback.print_exc()
            return make_server_error_response(str(e))

    def delete(self, request, uuid):
        res = {"code": 400, "message": "", "data": None}
        try:
            user_name = get_useraccount_from_request(request=request)
            user_name = get_user_from_useraccount(user_name)
            dimension = Dimension.objects.filter(
                uuid=uuid, valid_flag=True).first()
            if dimension is None:
                return make_delete_error_response(message="该条目不存在")

            used_flag, used_message = is_dimension_used(dimension)
            if used_flag:
                return make_delete_error_response(message=used_message)
            dimension.valid_flag = False
            dimension.modify_person = user_name
            dimension.save()
            return make_delete_success_response(data=None)
        except Exception as e:
            traceback.print_exc()
            return make_server_error_response(str(e))
